﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NCM_MSTest.Alg;

namespace NCM_MSTest.Test
{
    [TestClass]
    [TestCategory("线性方程组数值解法测试")]
    public class 线性方程组数值解测试
    {
        public static double[,] Example_3_1_A = new double[3, 3]
        {
            {1,1,1},
            {0,4,-1},
            {2,-2,1},
        };
        public static double[] Example_3_1_B = new double[3]
        {
            6,5,1
        };
        public static double[] Example_3_1_X = new double[3]
        {
            1,2,3
        };

        [TestMethod("直接解法 高斯消去法 3.1")]
        public void Example_3_1()
        {
            var A = Example_3_1_A;
            var B = Example_3_1_B;
            var X = Example_3_1_X;
            var rx = new double[X.Length];
            NumbericalSolutionOfLinearEquations.Direct_Gauss(A, B, ref rx);
            for (int i = 0; i < rx.Length; i++)
            {
                System.Diagnostics.Trace.WriteLine($"x_{i + 1} = \t {rx[i]}");
            }

            for (int i = 0; i < rx.Length; i++)
            {
                Assert.IsTrue(X[i].EqualsDelta(rx[i]));
            }
        }

        [TestMethod("直接解法 高斯-约当消去法 3.1")]
        public void Example_3_1_GJ()
        {
            var A = Example_3_1_A;
            var B = Example_3_1_B;
            var X = Example_3_1_X;
            var rx = new double[X.Length];
            NumbericalSolutionOfLinearEquations.Direct_GaussJordan(A, B, ref rx);
            for (int i = 0; i < rx.Length; i++)
            {
                System.Diagnostics.Trace.WriteLine($"x_{i + 1} = \t {rx[i]}");
            }

            for (int i = 0; i < rx.Length; i++)
            {
                Assert.IsTrue(X[i].EqualsDelta(rx[i]));
            }
        }

        public static double[,] Example_3_2_A = new double[10, 10]
        {
            {1,1,1,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,1,1,1},
            {-1,0,0,1,0,-1,0,0,0,0},
            {0,0,-1,0,1.0,0,0,0,-1.0,0},
            {0.0,0.0,0.0,0.0,0.0,1.0,1.0,0.0,0.0,-1},

            {0.0,0.0,0.0,0.0,0.0,0.0,-50.0,75.0,0.0,-50.0},
            {0.0,0.0,0.0,0.0,-100.0,0.0,0.0,75.0,-5.0,0.0},
            {0.0,10.0,-35.0,0.0,-100.0,0.0,0.0,0.0,0.0,0.0},
            {-1.0,10.0,0.0,-23.0,0.0,0.0,0.0,0.0,0.0,0.0},
            {0.0,0.0,0.0,-23.0,0.0,-25.0,50.0,0.0,0.0,0.0},
        };
        public static double[] Example_3_2_B = new double[10]
        {
            1,2,0,0,0,0,0,0,0,0
        };
        public static double[] Example_3_2_X = new double[10]
        {
            0.3776,1.2622,-0.6399,0.5324,0.3502,
            0.1548,0.3223,0.5329,0.9900,0.4771
        };

        [TestMethod("直接解法 高斯消去法 3.2")]
        public void Example_3_2()
        {
            var A = Example_3_2_A;
            var B = Example_3_2_B;
            var X = Example_3_2_X;
            var rx = new double[X.Length];
            NumbericalSolutionOfLinearEquations.Direct_Gauss(A, B, ref rx);
            for (int i = 0; i < rx.Length; i++)
            {
                System.Diagnostics.Trace.WriteLine($"x_{i + 1} = \t {rx[i]}");
            }

            for (int i = 0; i < rx.Length; i++)
            {
                Assert.IsTrue(X[i].EqualsDelta(rx[i], 1e-4));
            }
        }

        [TestMethod("直接解法 高斯-约当消去法 3.2")]
        public void Example_3_2_GJ()
        {
            var A = Example_3_2_A;
            var B = Example_3_2_B;
            var X = Example_3_2_X;
            var rx = new double[X.Length];
            NumbericalSolutionOfLinearEquations.Direct_GaussJordan(A, B, ref rx);
            for (int i = 0; i < rx.Length; i++)
            {
                System.Diagnostics.Trace.WriteLine($"x_{i + 1} = \t {rx[i]}");
            }

            for (int i = 0; i < rx.Length; i++)
            {
                Assert.IsTrue(X[i].EqualsDelta(rx[i], 1e-4));
            }
        }

        public static double[,] Example_3_4_A = new double[5, 5]
        {
            {1,1,0,0,0 },
            {1,2,1,0,0 },
            {0,1,3,1,0 },
            {0,0,1,4,1 },
            {0,0,0,1,5 },
        };

        public static double[] Example_3_4_B = new double[5]
        {
            3,8,15,24,29
        };

        public static double[] Example_3_4_X = new double[5]
        {
            1,2,3,4,5
        };

        [TestMethod("直接解法 追赶法 3.4")]
        public void Example_3_4_Trid()
        {
            var A = Example_3_4_A;
            var B = Example_3_4_B;
            var X = Example_3_4_X;
            var rx = new double[X.Length];
            NumbericalSolutionOfLinearEquations.Direct_Trid(A, B, ref rx);
            for (int i = 0; i < rx.Length; i++)
            {
                System.Diagnostics.Trace.WriteLine($"x_{i + 1} = \t {rx[i]}");
            }

            for (int i = 0; i < rx.Length; i++)
            {
                Assert.IsTrue(X[i].EqualsDelta(rx[i], 1e-4));
            }
        }

        public static double[,] Example_3_5_A = new double[3, 3]
        {
            {8,-3,2 },
            {4,11,-1 },
            {6,3,12 },
        };

        public static double[] Example_3_5_B = new double[3]
        {
            20,33,36
        };

        public static double[] Example_3_5_X = new double[3]
        {
            3,2,1
        };

        [TestMethod("迭代解法 雅可比迭代法 3.5")]
        public void Example_3_5()
        {
            var X = Example_3_5_X;
            var A1 = Example_3_5_A.CloneEx();
            var B1 = Example_3_5_B.CloneEx();
            var rx1 = new double[X.Length];

            var A2 = Example_3_5_A.CloneEx();
            var B2 = Example_3_5_B.CloneEx();
            var rx2 = new double[X.Length];

            int k1 = 0, k2 = 0;
            NumbericalSolutionOfLinearEquations.Iteration_Jacobi(A1, B1, ref rx1, out k1, 1e-4, 100);
            for (int i = 0; i < rx1.Length; i++)
            {
                System.Diagnostics.Trace.WriteLine($"x_{i + 1} = \t {rx1[i]}");
            }

            NumbericalSolutionOfLinearEquations.Iteration_Jacobi2(A2, B2, ref rx2, out k2, 1e-4, 100);
            for (int i = 0; i < rx2.Length; i++)
            {
                System.Diagnostics.Trace.WriteLine($"x_{i + 1} = \t {rx2[i]}");
            }
            for (int i = 0; i < rx1.Length; i++)
            {
                Assert.IsTrue(X[i].EqualsDelta(rx1[i], 1e-4));
            }
            for (int i = 0; i < rx2.Length; i++)
            {
                Assert.IsTrue(X[i].EqualsDelta(rx2[i], 1e-4));
            }
        }

        [TestMethod("迭代解法 高斯赛德尔迭代法 3.5")]
        public void Example_3_5_GS()
        {
            var X = Example_3_5_X;
            var A1 = Example_3_5_A.CloneEx();
            var B1 = Example_3_5_B.CloneEx();
            var rx1 = new double[X.Length];

            int k1 = 0;
            NumbericalSolutionOfLinearEquations.Iteration_GaussSeidel(A1, B1, ref rx1, out k1, 1e-4, 100);
            for (int i = 0; i < rx1.Length; i++)
            {
                System.Diagnostics.Trace.WriteLine($"x_{i + 1} = \t {rx1[i]}");
                System.Diagnostics.Trace.WriteLine($"X_{i + 1} = \t {X[i]}");
            }
            for (int i = 0; i < rx1.Length; i++)
            {
                Assert.IsTrue(X[i].EqualsDelta(rx1[i], 1e-4));
            }
        }

        public static double[,] Exer_3_1_A = new double[4, 4]
        {
            {0.4096,0.1234,0.3678,0.2943 },
            {0.2246,0.3872,0.4015,0.1129 },
            {0.3645,0.1920,0.3781,0.0643 },
            {0.1784,0.4002,0.2786,0.3927 },
        };

        public static double[] Exer_3_1_B = new double[4]
        {
            0.4043,0.1550,0.4240,-0.2557
        };

        [TestMethod("习题 3.1")]
        public void Exercise_3_1()
        {
            var a1 = Exer_3_1_A.CloneEx();
            var a2 = Exer_3_1_A.CloneEx();
            var a3 = Exer_3_1_A.CloneEx();
            var b1 = Exer_3_1_B.CloneEx();
            var b2 = Exer_3_1_B.CloneEx();
            var b3 = Exer_3_1_B.CloneEx();
            var rx1 = new double[4];
            var rx2 = new double[4];
            var rx3 = new double[4];

            NumbericalSolutionOfLinearEquations.Direct_Gauss(a1, b1, ref rx1);
            int k2 = 0, k3 = 0;
            NumbericalSolutionOfLinearEquations.Iteration_Jacobi(a2, b2, ref rx2, out k2);
            NumbericalSolutionOfLinearEquations.Iteration_GaussSeidel(a3, b3, ref rx3, out k3);
            for (int i = 0; i < rx1.Length; i++)
            {
                System.Diagnostics.Trace.WriteLine($"x_{i + 1} = \t {rx1[i]}");
                System.Diagnostics.Trace.WriteLine($"x_{i + 1} = \t {rx2[i]}");
                System.Diagnostics.Trace.WriteLine($"x_{i + 1} = \t {rx3[i]}");
            }
        }
    }
}
